#include "DynSphere.h"

DynSphere::DynSphere(const Vector3& _ocenter, float _radius, const rgb& _color, float _mintime, float _maxtime)
	: ocenter(_ocenter), radius(_radius), color(_color), mintime(_mintime), maxtime(_maxtime)
{

}

bool DynSphere::hit(const Ray& r, float tmin, float tmax, float time, HitRecord &record) const
{
	//	compute A, B and C
	Vector3 center = getCenter(time);
	Vector3 oc = r.origin() - center;

	float A = r.direction().squaredLength();
	float inv2A = 0.5f / A;
	float B = 2 * dot(r.direction(), oc);
	float C = oc.squaredLength() - radius * radius;

	//	compute delta
	float delta = B * B - 4 * A * C;
	if (delta <= 0.0f) return false;
	float sdelta = sqrt(delta);

	float t;
	//	if C is positive, compute the smaller root
	if (C > 0.0f)	
		t = inv2A * (-B - sdelta);
	else	// compute the bigger root
		t = inv2A * (-B + sdelta);
	if (t < tmin || t > tmax) return false;
	record.t = t;
	record.normal = (r(t) - center) / radius;
	//record.color = color;
	return true;

}

bool DynSphere::shadowHit(const Ray& r, float tmin, float tmax, float time) const
{
	Vector3 center = getCenter(time);
	//	compute A, B and C
	Vector3 oc = r.origin() - center;

	float A = r.direction().squaredLength();
	float inv2A = 0.5f / A;
	float B = 2 * dot(r.direction(), oc);
	float C = oc.squaredLength() - radius * radius;

	//	compute delta
	float delta = B * B - 4 * A * C;
	if (delta <= 0.0f) return false;
	float sdelta = sqrt(delta);

	float t;
	//	if C is positive, compute the smaller root
	if (C > 0.0f)	
		t = inv2A * (-B - sdelta);
	else	// compute the bigger root
		t = inv2A * (-B + sdelta);
	if (t < tmin || t > tmax) return false;
	return true;

}

//	the sphere moves in a straight line with v = 1.0
//	time ranges from [0, 1]
Vector3 DynSphere::getCenter(float time) const
{
	float realtime = time * maxtime + (1.0f - time) * mintime;
	return Vector3(ocenter.x() + realtime,
		ocenter.y() + realtime,
		ocenter.z() + realtime);
}